# coding=utf-8

import struct
from socket import *
import time, random, re
import binascii
import threading
import numpy as np
from src.tools import decode_hex, getMd5, encode_hex
from ftplib import FTP
import os


class Message:
    def __init__(self, vin):
        self.S_FLAG = [0x23, 0x23]
        self.C_FLAG = [0x01]
        self.R_FLAG = [0x01]
        self.VIN = vin.encode('ascii')
        self.E_FLAG = [0x01]
        self.D_LEN = [0x00, 0x00]
        self.D_DATA = bytes()
        self.BCC = 0x00

        self.bytes_message = bytes()

    def set_data(self, c_flag, r_flag, data):
        self.C_FLAG = [c_flag]
        self.R_FLAG = [r_flag]
        data_len = len(data)
        self.D_LEN = [(data_len >> 8) & 0xFF, data_len & 0xFF]
        self.D_DATA = data

    def get_message(self):
        self.bytes_message = bytes(self.S_FLAG) + bytes(self.C_FLAG) + \
                             bytes(self.R_FLAG) + self.VIN + \
                             bytes(self.E_FLAG) + bytes(self.D_LEN) + \
                             bytes(self.D_DATA)
        for b in self.bytes_message:
            self.BCC ^= b

        self.bytes_message += bytes([self.BCC])
        return self.bytes_message


class VehicleStatus:
    def __init__(self):
        self.status = 0x02
        self.charge = 0x03
        self.run_mode = 0x01
        self.speed = 0
        self.total_mileage = 10000
        self.total_voltage = 500
        self.total_current = 50
        self.SOC = 80
        self.DC = 0x01
        self.block = 0x01
        self.resistance = 999
        self.accelerate = 0
        self.braking = 0

        self.location_status = 0x00
        self.longitude = 0x00
        self.latitude = 0x00

    def get01hexdata(self):
        hexdata = '01' + '%02X' % self.status + '%02X' % self.charge + '%02X' % self.run_mode
        hexdata += '%04X' % int(self.speed * 10)
        hexdata += '%08X' % int(self.total_mileage * 10)
        hexdata += '%04X' % int(self.total_voltage * 10)
        hexdata += '%04X' % int(self.total_current * 10 + 10000)
        hexdata += '%02X' % self.SOC
        hexdata += '%02X' % self.DC
        hexdata += '%02X' % self.block
        hexdata += '%04X' % self.accelerate
        hexdata += '%02X' % self.block
        hexdata += '%02X' % self.braking
        return hexdata

    def get05hexdata(self):
        hexdata = '05'
        hexdata += '%02X' % self.location_status
        hexdata += '%08X' % int(self.longitude * 1000000)
        hexdata += '%08X' % int(self.latitude * 1000000)
        return hexdata

    def get07hexdata(self):
        hexdata = '07'
        hexdata += '000000000000000000'
        return hexdata

    def get_real_hex_data(self):
        return self.get01hexdata() + self.get05hexdata() + self.get07hexdata()


class RoadInfo:
    def __init__(self):
        self.id = 0
        self.radius = 0
        self.latitude = 0
        self.longitude = 0
        self.width = 0
        self.speed = 0


class FTPInfo:
    def __init__(self):
        self.channel = 0
        self.count = 0
        self.interval = 0
        self.ip = ''
        self.port = 0
        self.username = ''
        self.password = ''
        self.path = ''


class Terminal:
    def __init__(self, host='172.16.6.78', port=5055, vin='LSVHJ233022221761', iccid='123456789abcdef12345'):
        self.CMD_MSG = {0x01: ['车辆登入', None, self.reply_login], \
                        0x02: ['事实上报', None, None], \
                        0x03: ['补发信息', None, None], \
                        0x04: ['车辆登出', None, None], \
                        0x05: ['', None, None], \
                        0x06: ['', None, None], \
                        0x07: ['心跳', None, None], \
                        0x08: ['校时', None, None], \
                        0x80: ['查询', self.process_query, None], \
                        0x81: ['设置', self.process_set, None], \
                        0x82: ['控制', self.process_ctrl, None], \
                        0xD0: ['远程控制模式设置', self.process_d0, None],
                        0xD1: ['随机数上报', None, None],
                        0xD2: ['授权码下发', self.process_d2, None],
                        0xD3: ['远程控制状态上报', None, None],
                        0xD4: ['远程控制结果上报', None, None],
                        0xD5: ['远程控制状态应答', self.process_d5, None],
                        0xD6: ['行车路线下发', self.process_d6, None],
                        0xD7: ['泊车指令下发', self.process_d7, None],
                        0xD8: ['业务指令下发', self.process_d8, None],
                        0xD9: ['指令执行控制', self.process_d9, None],
                        0xDA: ['拍照上传下发', self.process_da, None]}
        self.SUB_CMD_CTRL = {0x01: '远程升级', \
                             0x02: '关机', \
                             0x03: '复位', \
                             0x04: '恢复出厂设置', \
                             0x05: '断开链路', \
                             0x06: '报警', \
                             0x07: '开启链路检测'}
        self.SUB_CMD_PARAM = {0x01: ['车载终端本地存储时间周期', 0, self.__decode_word, self.__encode_word], \
                              0x02: ['正常时信息上报时间周期', 0, self.__decode_word, self.__encode_word], \
                              0x03: ['报警时信息上报时间周期', 0, self.__decode_word, self.__encode_word], \
                              0x04: ['远程服务与管理平台域名长度', 4, self.__decode_byte, self.__encode_byte], \
                              0x05: ['远程服务与管理平台域名', 'SXQC', self.__get_string, self.__encode_string], \
                              0x06: ['远程服务与管理平台端口', 22, self.__decode_word, self.__encode_word], \
                              0x07: ['硬件版本', 'ABC12', self.__get_string, self.__encode_string], \
                              0x08: ['固件版本', 'DEC12', self.__get_string, self.__encode_string], \
                              0x09: ['车载终端心跳发送周期', 0, self.__decode_byte, self.__encode_byte], \
                              0x0A: ['终端应答超时时间', 0, self.__decode_word, self.__encode_word], \
                              0x0B: ['平台应答超时时间', 0, self.__decode_word, self.__encode_word], \
                              0x0C: ['时间间隔', 0, self.__decode_byte, self.__encode_byte], \
                              0x0D: ['公共平台域名长度', 4, self.__decode_byte, self.__encode_byte], \
                              0x0E: ['公共平台域名', 'SXQC', self.__get_string, self.__encode_string], \
                              0x0F: ['公共平台端口', 33, self.__decode_word, self.__encode_word], \
                              0x10: ['否处于抽样检测中', 0, self.__decode_byte, self.__encode_byte], \
                              0x80: ['操作授权码', 16, self.__get_hex_str, self.__encode_byte], \
                              0x81: ['密钥更新', 256, self.__get_hex_str, self.__encode_byte]}

        self.STATUS = VehicleStatus()
        self.HOST = host
        self.PORT = port
        self.VIN = vin
        self.ICCID = iccid
        self.sock = socket(AF_INET, SOCK_STREAM)
        self.RUN = True
        self.ROADS = [0, 0, []]  # id,count,road
        self.AUTOPILOT = {}
        self.FTP = FTPInfo()

    def start(self):
        self.RUN = True
        if self.connect_server():
            self.login()
            # pass

    def stop(self):
        self.RUN = False
        self.sock.close()

    def connect_server(self):
        try:
            self.sock.connect((self.HOST, self.PORT))
            thread = threading.Thread(target=self.recv_data, args=())
            thread.start()
        except Exception as e:
            print("Connet Server Fail! %s", e)
            return False
        return True

    def recv_data(self):
        while self.RUN:
            buffer = self.sock.recv(99999)
            if buffer:
                print("\nRECV:", binascii.b2a_hex(buffer))
                if buffer[3] != 0xFE:
                    print("收到应答：", self.CMD_MSG[buffer[2]][0], " RESULT:", buffer[3])
                    if self.CMD_MSG[buffer[2]][2]:
                        self.CMD_MSG[buffer[2]][2](buffer)
                else:
                    print("收到命令：", self.CMD_MSG[buffer[2]][0])
                    if self.CMD_MSG[buffer[2]][1]:
                        self.CMD_MSG[buffer[2]][1](buffer)

    def auto_send_real_info(self):
        count = 0
        while self.RUN:
            body = self.STATUS.get_real_hex_data()
            self.send_reainfo(0x02, 0xFE, bytearray.fromhex(body))
            time.sleep(10)
            count += 1
            if count == 10:
                count = 0
                self.send_heartbeat()

    def reply_login(self, data):
        if data[3] == 0x01:
            # 登录成功
            thread = threading.Thread(target=self.auto_send_real_info, args=())
            thread.start()
        else:
            print("\t登录失败！！！！")
            self.RUN = False
            self.stop()

    def process_query(self, data):
        print("\t查询参数个数:", data[30])
        values = []
        for i in range(data[30]):
            values.append(self.SUB_CMD_PARAM[data[31 + i]][:2])
        print("\t查询数据：", values)

        data_body = bytes()
        data_item_len = 0
        for i in range(data[30]):
            pid = data[31 + i]
            if pid == 0x05:
                data_body += bytes([0x04])
                data_body += self.SUB_CMD_PARAM[0x04][3](self.SUB_CMD_PARAM[0x04][1])
                data_item_len += 1
            elif pid == 0x0E:
                data_body += bytes([0x0D])
                data_body += self.SUB_CMD_PARAM[0x0D][3](self.SUB_CMD_PARAM[0x0D][1])
                data_item_len += 1
            data_body += bytes([pid])
            data_body += self.SUB_CMD_PARAM[pid][3](self.SUB_CMD_PARAM[pid][1])
            data_item_len += 1
        msg = Message(self.VIN)
        new_data = data[24:24 + 6] + bytes([data_item_len]) + data_body
        msg.set_data(data[2], 0x01, new_data)
        self.send_msg(msg)

    def process_set(self, data):
        print("\t设置参数个数:", data[30])
        values = []
        pids = []
        start_index = 31
        for i in range(data[30]):
            pid = data[start_index]
            pids.append(pid)
            start_index += 1
            if pid == 0x07 or pid == 0x08:
                size, value = self.SUB_CMD_PARAM[pid][2](data[start_index:], 5)
                self.SUB_CMD_PARAM[pid][1] = value
                start_index += size
            elif pid == 0x05:
                d_len = self.SUB_CMD_PARAM[0x04][1]
                size, value = self.SUB_CMD_PARAM[pid][2](data[start_index:], d_len)
                self.SUB_CMD_PARAM[pid][1] = value
                start_index += size
            elif pid == 0x0E:
                d_len = self.SUB_CMD_PARAM[0x0D][1]
                size, value = self.SUB_CMD_PARAM[pid][2](data[start_index:], d_len)
                self.SUB_CMD_PARAM[pid][1] = value
                start_index += size
            elif pid == 0x80:
                d_len = 16
                size, value = self.SUB_CMD_PARAM[pid][2](data[start_index:], d_len)
                self.SUB_CMD_PARAM[pid][1] = value
                start_index += size
            elif pid == 0x81:
                d_len = 256
                size, value = self.SUB_CMD_PARAM[pid][2](data[start_index:], d_len)
                self.SUB_CMD_PARAM[pid][1] = value
                start_index += size
            else:
                size, value = self.SUB_CMD_PARAM[pid][2](data[start_index:])
                self.SUB_CMD_PARAM[pid][1] = value
                start_index += size

        for p in pids:
            values.append(self.SUB_CMD_PARAM[p][:2])

        print("\t设置数据：", values)
        self.send_universal(data)

    def process_ctrl(self, data):
        print("\t子命令 ID:", data[30])
        if data[30] == 0x06:
            print("\t子命令：", self.SUB_CMD_CTRL[data[30]], " 告警等级：", data[-2])
        elif data[30] == 0x01:
            print("\t子命令：", self.SUB_CMD_CTRL[data[30]])
            prarms_data = data[31:]
            print("\t", self.__decode_upgrade_prarms(prarms_data))
        else:
            print("\t子命令：", self.SUB_CMD_CTRL[data[30]])
        self.send_universal(data)

    def process_d0(self, data):
        date, sn, de_body = self.__decode_msg_body(data)
        print("\t指令：", de_body)
        body_bytes = bytearray.fromhex(de_body)
        if body_bytes[0] == 0x00:
            print("车辆远程唤醒")
        elif body_bytes[0] == 0x01:
            print("车辆远程休眠")
        elif body_bytes[0] == 0x10:
            print("无人驾驶模式")
        elif body_bytes[0] == 0x11:
            print("人工驾驶模式")
        elif body_bytes[0] == 0x20:
            print("车辆远程启动")
            self.STATUS.status = 0x01
        elif de_body[0] == 0x21:
            print("车辆远程熄火")
            self.STATUS.status = 0x02

        self.send_random_seed(date, sn)

    def process_d2(self, data):
        date, sn, de_body = self.__decode_msg_body(data)
        cmd_sn = de_body[0:4]
        print("\t任务流水号：", cmd_sn)
        print("\t随机数流水号：", de_body[4:8])
        print("\t授权码：", de_body[8:])

        if self.AUTOPILOT.get(cmd_sn, None):
            thread = threading.Thread(target=self.AUTOPILOT[cmd_sn], args=([date, cmd_sn]))
            thread.start()
        else:
            self.send_exec_status(date, cmd_sn, '01')
            self.send_exec_status(date, cmd_sn, '02')
            self.send_exec_status(date, cmd_sn, '03')
            self.send_exec_result(date, cmd_sn, '11')

    def run_road(self, date, cmd_sn):
        print("run_road")
        self.send_exec_status(date, cmd_sn, '01')
        self.send_exec_status(date, cmd_sn, '02')
        for r in self.ROADS[2]:
            speed = np.linspace(self.STATUS.speed, r.speed, 10)
            longitude = np.linspace(self.STATUS.longitude, r.longitude, 10)
            latitude = np.linspace(self.STATUS.latitude, r.latitude, 10)
            for i in range(10):
                self.STATUS.speed = speed[i]
                self.STATUS.longitude = longitude[i]
                self.STATUS.latitude = latitude[i]
                time.sleep(1)
            # self.STATUS.speed = r.speed
            # self.STATUS.longitude = r.longitude
            # self.STATUS.latitude = r.latitude
            # time.sleep(1)
        self.STATUS.speed = 0
        self.send_exec_status(date, cmd_sn, '03')
        self.send_exec_result(date, cmd_sn, '11')

    def run_upload_pictiure(self, date, cmd_sn):
        print("run_upload_pictiure")
        self.send_exec_status(date, cmd_sn, '01')
        self.send_exec_status(date, cmd_sn, '02')
        ftp = FTP()
        ftp.set_debuglevel(2)
        ftp.connect(self.FTP.ip, self.FTP.port)
        ftp.login(self.FTP.username, self.FTP.password)
        print(ftp.getwelcome())
        ftp.cwd(self.FTP.path)
        fp = open(os.path.join("../upload", "1.png"), 'rb')
        remotepath = self.VIN + "_1.png"
        ftp.storbinary('STOR ' + remotepath, fp, 1024)
        ftp.set_debuglevel(0)
        fp.close()

        fp = open(os.path.join("../upload", "2.png"), 'rb')
        remotepath = self.VIN + "_2.png"
        ftp.storbinary('STOR ' + remotepath, fp, 1024)
        ftp.set_debuglevel(0)
        fp.close()

        self.send_exec_status(date, cmd_sn, '03')
        self.send_exec_result(date, cmd_sn, '11')

    def process_d5(self, data):
        date, sn, de_body = self.__decode_msg_body(data)
        cmd_sn = de_body[0:4]
        print("\t任务流水号：", cmd_sn)
        print("\t状态应答：", de_body[4:6])

    def process_d6(self, data):
        date, sn, de_body = self.__decode_msg_body(data)
        print("\t路线：", de_body)
        de_body_bytes = bytearray.fromhex(de_body)
        self.ROADS[0] = int.from_bytes(de_body_bytes[0:4], byteorder='big', signed=False)
        self.ROADS[1] = int.from_bytes(de_body_bytes[4:6], byteorder='big', signed=False)
        self.ROADS[2] = []
        offset = 6
        for i in range(self.ROADS[1]):
            ri = RoadInfo()
            ri.id = int.from_bytes(de_body_bytes[offset:offset + 4], byteorder='big', signed=False)
            offset += 4
            ri.radius = int.from_bytes(de_body_bytes[offset:offset + 4], byteorder='big', signed=False)
            offset += 4
            ri.latitude = int.from_bytes(de_body_bytes[offset:offset + 4], byteorder='big', signed=False)
            ri.latitude = ri.latitude / 1000000.0
            offset += 4
            ri.longitude = int.from_bytes(de_body_bytes[offset:offset + 4], byteorder='big', signed=False)
            ri.longitude = ri.longitude / 1000000.0
            offset += 4
            ri.width = int.from_bytes(de_body_bytes[offset:offset + 2], byteorder='big', signed=False)
            offset += 2
            ri.speed = int.from_bytes(de_body_bytes[offset:offset + 2], byteorder='big', signed=False)
            offset += 2
            self.ROADS[2].append(ri)
        self.STATUS.longitude = self.ROADS[2][0].longitude
        self.STATUS.latitude = self.ROADS[2][0].latitude
        self.AUTOPILOT[sn] = self.run_road
        self.send_random_seed(date, sn)

    def process_d7(self, data):
        date, sn, de_body = self.__decode_msg_body(data)
        print("\t泊车：", de_body)
        self.send_random_seed(date, sn)

    def process_d8(self, data):
        date, sn, de_body = self.__decode_msg_body(data)
        print("\t业务：", de_body)
        self.send_random_seed(date, sn)

    def process_d9(self, data):
        date, sn, de_body = self.__decode_msg_body(data)
        print("\t过程：", de_body)
        self.send_random_seed(date, sn)

    def process_da(self, data):
        date, sn, de_body = self.__decode_msg_body(data)
        print("\t拍照：", de_body)
        # 01000800023137322e31362e382e393100182461646d696e004368616e67656d655f313233002f766964656f00
        de_body_bytes = bytearray.fromhex(de_body)
        self.FTP.channel = int(de_body_bytes[0])
        self.FTP.count = int.from_bytes(de_body_bytes[1:1 + 2], byteorder='big', signed=False)
        self.FTP.interval = int.from_bytes(de_body_bytes[3:3 + 2], byteorder='big', signed=False)
        index = de_body_bytes[5:].index(0x00)
        self.FTP.ip = de_body_bytes[5:5 + index].decode()
        self.FTP.port = int.from_bytes(de_body_bytes[5 + index + 1:5 + index + 1 + 2], byteorder='big', signed=False)
        start_index = 5 + index + 1 + 2
        index = de_body_bytes[start_index:].index(0x00)
        self.FTP.username = de_body_bytes[start_index:start_index + index].decode()
        start_index = start_index + index + 1
        index = de_body_bytes[start_index:].index(0x00)
        self.FTP.password = de_body_bytes[start_index:start_index + index].decode()
        start_index = start_index + index + 1
        index = de_body_bytes[start_index:].index(0x00)
        self.FTP.path = de_body_bytes[start_index:start_index + index].decode()

        self.send_random_seed(date, sn)
        self.AUTOPILOT[sn] = self.run_upload_pictiure

    def send_universal(self, data, result=0x01):
        # 只保留时间
        data_body = data[24:24 + 6]
        msg = Message(self.VIN)
        msg.set_data(data[2], result, data_body)
        self.send_msg(msg)

    def send_msg(self, msg):
        msg_bytes = msg.get_message()
        print("SEND:", msg_bytes.hex())
        self.sock.send(msg_bytes)

    def send_raw_msg(self, msg_bytes):
        print("SEND:", msg_bytes.hex())
        self.sock.send(msg_bytes)

    def login(self):
        print("LOGIN:")
        login_body = self.__get_nowtime_bytes() + \
                     bytes([0x00, 0x01]) + self.ICCID.encode('ascii') + \
                     bytes([0x10, 0x00])

        msg = Message(self.VIN)
        msg.set_data(0x01, 0xFE, login_body)
        self.send_msg(msg)

    def send_reainfo(self, cmd, result, data_body):
        msg = Message(self.VIN)
        date = self.__get_nowtime_bytes()
        msg.set_data(cmd, result, date + data_body)
        self.send_msg(msg)

    def send_heartbeat(self):
        msg = Message(self.VIN)
        msg.set_data(0x07, 0xFE, bytes([]))
        self.send_msg(msg)

    def send_random_seed(self, date, cmd_sn):
        rep_body = cmd_sn + "00000001"  # 随机数
        print("random_seed", rep_body)
        body = self.__encode_msg_body(date, 1, rep_body)
        msg = Message(self.VIN)
        msg.E_FLAG = [0x02]
        msg.set_data(0xD1, 0x01, bytes.fromhex(body))
        self.send_msg(msg)

    def send_exec_status(self, date, cmd_sn, status='01'):
        rep_body = cmd_sn + status
        print("exec_status", rep_body)
        body = self.__encode_msg_body(date, 1, rep_body)
        msg = Message(self.VIN)
        msg.E_FLAG = [0x02]
        msg.set_data(0xD3, 0x01, bytes.fromhex(body))
        self.send_msg(msg)

    def send_exec_result(self, date, cmd_sn, result='01', reson='00'):
        rep_body = cmd_sn + result + reson
        print("exec_status", rep_body)
        body = self.__encode_msg_body(date, 1, rep_body)
        msg = Message(self.VIN)
        msg.E_FLAG = [0x02]
        msg.set_data(0xD4, 0x01, bytes.fromhex(body))
        self.send_msg(msg)

    def __decode_upgrade_prarms(self, prarms_data):
        offset = 0;
        end_index, diaName = self.__get_string(prarms_data[offset:])
        offset += end_index + 1
        end_index, userName = self.__get_string(prarms_data[offset:])
        offset += end_index + 1
        end_index, passWord = self.__get_string(prarms_data[offset:])
        offset += end_index + 1
        ip_str = self.__get_ip(prarms_data[offset:])
        offset += 6 + 1
        port = prarms_data[offset] * 256 + prarms_data[offset + 1]
        offset += 2 + 1
        end_index, manufactureID = self.__get_string(prarms_data[offset:], 4)
        offset += 4 + 1
        end_index, firmwareVersion = self.__get_string(prarms_data[offset:], 5)
        offset += 5 + 1
        end_index, softwareVersion = self.__get_string(prarms_data[offset:], 5)
        offset += 5 + 1
        end_index, url = self.__get_string(prarms_data[offset:])
        offset += end_index + 1
        timeout = prarms_data[offset] * 256 + prarms_data[offset + 1]
        return (
            diaName, userName, passWord, ip_str, port, manufactureID, firmwareVersion, softwareVersion, url, timeout)

    def __get_hex_str(self, sub_data, size):
        return (size, sub_data[:size].hex())

    def __get_string(self, sub_data, size=None, end_char=0x3B):
        buffer = bytes()
        if size == None:
            for i in range(len(sub_data)):
                if sub_data[i] != end_char:
                    continue
                else:
                    buffer = sub_data[:i]
                    return (i, buffer.decode('ascii'))
        else:
            buffer = sub_data[:size]
            return (size, buffer.decode('ascii'))

    def __get_ip(self, sub_data):
        return "%d.%d.%d.%d" % (sub_data[2], sub_data[3], sub_data[4], sub_data[5])

    def __get_nowtime_bytes(self):
        t = time.localtime(time.time())
        time_byte = bytes([17, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec])
        return time_byte

    def __decode_word(self, sub_data):
        return (2, sub_data[0] * 256 + sub_data[1])

    def __encode_word(self, word):
        return bytes([(word >> 8) & 0xFF, word & 0xFF])

    def __decode_byte(self, sub_data):
        return (1, sub_data[0])

    def __encode_byte(self, value):
        return bytes([value])

    def __encode_string(self, value):
        return value.encode('ascii')

    def __decode_msg_body(self, data):
        date = data[24:30].hex()
        sn = data[30:32].hex()
        body_len = self.__decode_word(data[32:34])[1]
        md5 = data[34:50].hex()
        en_body_len = self.__decode_word(data[50:52])[1]
        en_body = data[52:-1].hex()
        print("date", date, "sn", sn, "body_len", body_len, "md5", md5, "en_body_len", en_body_len)
        print("en_body", en_body)
        de_body = decode_hex(en_body, body_len)
        print("de_body", de_body)
        calc_md5 = getMd5(de_body)
        if md5 != calc_md5:
            print("check md5 fail!")
        return date, sn, de_body

    def __encode_msg_body(self, date, sn, hex_body):
        encode_msg = ''
        md5 = getMd5(hex_body)
        rep_en_body = encode_hex(hex_body)
        hex_sn = "%04x" % (int(sn))
        de_body_len = "%04x" % (int(len(hex_body) / 2))
        en_body_len = "%04x" % (int(len(rep_en_body) / 2))

        encode_msg = date + hex_sn + de_body_len + md5 + en_body_len + rep_en_body
        return encode_msg
